{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "from torch.nn import init\n",
    "from PIL import Image\n",
    "import torchvision\n",
    "from torch.autograd import Variable\n",
    "import torchvision.transforms as transforms\n",
    "import torch.optim as optim\n",
    "from torch.utils.data import DataLoader\n",
    "import math\n",
    "import os\n",
    "import matplotlib.pylab as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ChannelAttention(nn.Module):\n",
    "    def __init__(self, in_planes, ratio=16):\n",
    "        super(ChannelAttention, self).__init__()\n",
    "        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n",
    "        self.max_pool = nn.AdaptiveMaxPool2d(1)\n",
    "        self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)\n",
    "        self.sigmoid = nn.Sigmoid()\n",
    "\n",
    "    def forward(self, x):\n",
    "        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))\n",
    "        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))\n",
    "        out = avg_out + max_out\t\t# 这里并没有使用到论文中的shared MLP, 而是直接相加了\n",
    "        return self.sigmoid(out)\n",
    "\n",
    "\n",
    "class SpatialAttention(nn.Module):\n",
    "    def __init__(self, kernel_size=7):\n",
    "        super(SpatialAttention, self).__init__()\n",
    "        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'\n",
    "        padding = 3 if kernel_size == 7 else 1\n",
    "        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)\n",
    "        self.sigmoid = nn.Sigmoid()\n",
    "\n",
    "    def forward(self, x):\n",
    "        avg_out = torch.mean(x, dim=1, keepdim=True)\n",
    "        max_out, _ = torch.max(x, dim=1, keepdim=True)\n",
    "        x = torch.cat([avg_out, max_out], dim=1)\n",
    "        x = self.conv1(x)\n",
    "        return self.sigmoid(x)\n",
    "def conv3x3(in_planes, out_planes, stride=1):\n",
    "    \"3x3 convolution with padding\"\n",
    "    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n",
    "                     padding=1, bias=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Hswish(x,inplace=True):\n",
    "    return x * F.relu6(x + 3., inplace=inplace) / 6.\n",
    "\n",
    "def Hsigmoid(x,inplace=True):\n",
    "    return F.relu6(x + 3., inplace=inplace) / 6.\n",
    "\n",
    "\n",
    "# Squeeze-And-ExciteÄ£¿é\n",
    "class SEModule(nn.Module):\n",
    "    def __init__(self, channel, reduction=4):\n",
    "        super(SEModule, self).__init__()\n",
    "        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n",
    "        self.se = nn.Sequential(\n",
    "            nn.Linear(channel, channel // reduction, bias=False),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Linear(channel // reduction, channel, bias=False),\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        b, c, _, _ = x.size()\n",
    "        y=self.avg_pool(x).view(b, c)\n",
    "        y=self.se(y)\n",
    "        y = Hsigmoid(y).view(b, c, 1, 1)\n",
    "        return x * y.expand_as(x)\n",
    "\n",
    "class Bottleneck(nn.Module):\n",
    "    def __init__(self,in_channels,out_channels,kernel_size,exp_channels,stride,se='True',nl='HS'):\n",
    "        super(Bottleneck, self).__init__()\n",
    "        padding = (kernel_size - 1) // 2\n",
    "        if nl == 'RE':\n",
    "            self.nlin_layer = F.relu6\n",
    "        elif nl == 'HS':\n",
    "            self.nlin_layer = Hswish\n",
    "        self.stride=stride\n",
    "        if se:\n",
    "            self.se=SEModule(exp_channels)\n",
    "        else:\n",
    "            self.se=None\n",
    "        self.conv1=nn.Conv2d(in_channels,exp_channels,kernel_size=1,stride=1,padding=0,bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(exp_channels)\n",
    "        self.conv2=nn.Conv2d(exp_channels,exp_channels,kernel_size=kernel_size,stride=stride,\n",
    "                             padding=padding,groups=exp_channels,bias=False)\n",
    "        self.bn2=nn.BatchNorm2d(exp_channels)\n",
    "        self.conv3=nn.Conv2d(exp_channels,out_channels,kernel_size=1,stride=1,padding=0,bias=False)\n",
    "        self.bn3=nn.BatchNorm2d(out_channels)\n",
    "        # ÏÈ³õÊ¼»¯Ò»¸ö¿ÕÐòÁÐ£¬Ö®ºó¸ÄÔìÆä³ÉÎª²Ð²îÁ´½Ó\n",
    "        self.shortcut = nn.Sequential()\n",
    "        # Ö»ÓÐ²½³¤Îª1ÇÒÊäÈëÊä³öÍ¨µÀ²»ÏàÍ¬Ê±²Å²ÉÓÃÌøÔ¾Á¬½Ó(ÏëÒ»ÏÂÌøÔ¾Á´½ÓµÄ¹ý³Ì£¬ÊäÈëÊä³öÍ¨µÀÏàÍ¬Õâ¸öÌøÔ¾Á¬½Ó¾ÍÃ»ÒâÒåÁË)\n",
    "        if stride == 1 and in_channels != out_channels:\n",
    "            self.shortcut = nn.Sequential(\n",
    "                # ÏÂÃæµÄ²Ù×÷¾í»ý²»¸Ä±ä³ß´çºÍÍ¨µÀÊý\n",
    "                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=False),\n",
    "                nn.BatchNorm2d(out_channels)\n",
    "            )\n",
    "\n",
    "    def forward(self,x):\n",
    "        out=self.nlin_layer(self.bn1(self.conv1(x)))\n",
    "        if self.se is not None:\n",
    "            out=self.bn2(self.conv2(out))\n",
    "            out=self.nlin_layer(self.se(out))\n",
    "        else:\n",
    "            out = self.nlin_layer(self.bn2(self.conv2(out)))\n",
    "        out = self.bn3(self.conv3(out))\n",
    "        out = out + self.shortcut(x) if self.stride == 1 else out\n",
    "        return out\n",
    "\n",
    "\n",
    "class MobileNetV3_large(nn.Module):\n",
    "    # (out_channels,kernel_size,exp_channels,stride,se,nl)\n",
    "    cfg=[\n",
    "        (16,3,16,1,False,'RE'),\n",
    "        (24,3,64,2,False,'RE'),\n",
    "        (24,3,72,1,False,'RE'),\n",
    "        (40,5,72,2,True,'RE'),\n",
    "        (40,5,120,1,True,'RE'),\n",
    "        (40,5,120,1,True,'RE'),\n",
    "        (80,3,240,2,False,'HS'),\n",
    "        (80,3,200,1,False,'HS'),\n",
    "        (80,3,184,1,False,'HS'),\n",
    "        (80,3,184,1,False,'HS'),\n",
    "        (112,3,480,1,True,'HS'),\n",
    "        (112,3,672,1,True,'HS'),\n",
    "        (160,5,672,2,True,'HS'),\n",
    "        (160,5,960,1,True,'HS'),\n",
    "        (160,5,960,1,True,'HS')\n",
    "    ]\n",
    "    def __init__(self,num_classes=5):\n",
    "        super(MobileNetV3_large,self).__init__()\n",
    "        self.conv1=nn.Conv2d(3,16,3,2,padding=1,bias=False)\n",
    "        self.bn1=nn.BatchNorm2d(16)\n",
    "        # ¸ù¾ÝcfgÊý×é×Ô¶¯Éú³ÉËùÓÐµÄBottleneck²ã\n",
    "        self.layers = self._make_layers(in_channels=16)\n",
    "        self.conv2=nn.Conv2d(160,960,1,stride=1,bias=False)\n",
    "        self.bn2=nn.BatchNorm2d(960)\n",
    "        # ¾í»ýºó²»¸úBN£¬¾ÍÓ¦¸Ã°ÑbiasÉèÖÃÎªTrue\n",
    "        self.conv3=nn.Conv2d(960,1280,1,1,padding=0,bias=True)\n",
    "        self.conv4=nn.Conv2d(1280,num_classes,1,stride=1,padding=0,bias=True)\n",
    "\n",
    "    def _make_layers(self,in_channels):\n",
    "        layers=[]\n",
    "        for out_channels,kernel_size,exp_channels,stride,se,nl in self.cfg:\n",
    "            layers.append(\n",
    "                Bottleneck(in_channels,out_channels,kernel_size,exp_channels,stride,se,nl)\n",
    "            )\n",
    "            in_channels=out_channels\n",
    "        return nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self,x):\n",
    "        out=Hswish(self.bn1(self.conv1(x)))\n",
    "        out=self.layers(out)\n",
    "        out=Hswish(self.bn2(self.conv2(out)))\n",
    "        out=F.avg_pool2d(out,7)\n",
    "        out=Hswish(self.conv3(out))\n",
    "        out=self.conv4(out)\n",
    "        # ÒòÎªÔ­ÂÛÎÄÖÐ×îºóÒ»²ãÊÇ¾í»ý²ãÀ´ÊµÏÖÈ«Á¬½ÓµÄÐ§¹û£¬Î¬¶ÈÊÇËÄÎ¬µÄ£¬ºóÁ½Î¬ÊÇ1£¬ÔÚ¼ÆËãËðÊ§º¯ÊýµÄÊ±ºòÒªÇó¶þÎ¬£¬Òò´ËÔÚÕâÀïÐèÒª×öÒ»¸öresize\n",
    "        a,b=out.size(0),out.size(1)\n",
    "        out=out.view(a,b)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def _make_divisible(v, divisor, min_value=None):\n",
    "    if min_value is None:\n",
    "        min_value = divisor\n",
    "    new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)\n",
    "    # Make sure that round down does not go down by more than 10%.\n",
    "    if new_v < 0.9 * v:\n",
    "        new_v += divisor\n",
    "    return new_v\n",
    "\n",
    "class h_sigmoid(nn.Module):\n",
    "    def __init__(self, inplace=True):\n",
    "        super(h_sigmoid, self).__init__()\n",
    "        self.relu = nn.ReLU6(inplace=inplace)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.relu(x + 3) / 6\n",
    "\n",
    "\n",
    "class h_swish(nn.Module):\n",
    "    def __init__(self, inplace=True):\n",
    "        super(h_swish, self).__init__()\n",
    "        self.sigmoid = h_sigmoid(inplace=inplace)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return x * self.sigmoid(x)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def conv31(ip,op,stride=1):\n",
    "    return nn.Conv2d(ip,op,kernel_size=3,stride=stride,padding=1,bias=False)\n",
    "def conv32(ip,op,stride=2):\n",
    "    return nn.Conv2d(ip,op,kernel_size=3,stride=stride,padding=1,bias=False)\n",
    "class Upsample(nn.Module):\n",
    "    def __init__(self,ip,op):\n",
    "        super(Upsample,self).__init__()\n",
    "        self.upsample=nn.Sequential(\n",
    "            conv31(ip,op,1),\n",
    "            nn.Upsample(scale_factor=2,mode='nearest')\n",
    "        )\n",
    "        \n",
    "    def forward(self,x):\n",
    "        x=self.upsample(x)\n",
    "        return x\n",
    "def backward_hook(module,grad_in,grad_out):\n",
    "    grad_block.append(grad_out[0].detach())\n",
    "\n",
    "def farward_hook(module,input,output):\n",
    "    fmap_block.append(output)\n",
    "\n",
    "    \n",
    "def backward2_hook(module,grad_in,grad_out):\n",
    "    grad_block2.append(grad_out[0].detach())\n",
    "def backward3_hook(module,grad_in,grad_out):\n",
    "    grad_block3.append(grad_out[0].detach())\n",
    "fmap_block=[]\n",
    "grad_block=[]\n",
    "grad_block2=[]\n",
    "grad_block3=[]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Confusion_mxtrix(labels, predicted, num_classes):\n",
    "    \"\"\"\n",
    "    混淆矩阵定义\n",
    "    Args:\n",
    "        labels: [number_total_pictures,1]\n",
    "        predicted: [number_total_pictures,1] \n",
    "        num_classes: 分类数目\n",
    "\n",
    "    Returns: Confusion_matrix\n",
    "    \"\"\"\n",
    "    Cmatrixs = torch.zeros((num_classes,num_classes))\n",
    "    stacked = torch.stack((labels, predicted), dim=1)\n",
    "    for s in stacked:\n",
    "        a, b = s.tolist()\n",
    "        Cmatrixs[a, b] = Cmatrixs[a, b] + 1\n",
    "    return Cmatrixs\n",
    "def plot_confusion_matrix(cm, savename, title='Confusion Matrix'):\n",
    "    \n",
    "    classes = ('NO DR', 'Mild', 'Moderate', 'Severe', 'Proliferative')\n",
    "    plt.figure(figsize=(12, 8), dpi=100)\n",
    "    np.set_printoptions(precision=2)\n",
    "\n",
    "    # 在混淆矩阵中每格的概率值\n",
    "    ind_array = np.arange(len(classes))\n",
    "    x, y = np.meshgrid(ind_array, ind_array)\n",
    "    for x_val, y_val in zip(x.flatten(), y.flatten()):\n",
    "        c = cm[y_val][x_val]\n",
    "        if c > 0.001:\n",
    "            plt.text(x_val, y_val, \"%0.2f\" % (c,), color='red', fontsize=15, va='center', ha='center')\n",
    "\n",
    "    plt.imshow(cm, interpolation='nearest', cmap=plt.cm.binary)\n",
    "    plt.title(title)\n",
    "    plt.colorbar()\n",
    "    xlocations = np.array(range(len(classes)))\n",
    "    plt.xticks(xlocations, classes, rotation=90)\n",
    "    plt.yticks(xlocations, classes)\n",
    "    plt.ylabel('Actual label')\n",
    "    plt.xlabel('Predict label')\n",
    "\n",
    "    # offset the tick\n",
    "    tick_marks = np.array(range(len(classes))) + 0.5\n",
    "    plt.gca().set_xticks(tick_marks, minor=True)\n",
    "    plt.gca().set_yticks(tick_marks, minor=True)\n",
    "    plt.gca().xaxis.set_ticks_position('none')\n",
    "    plt.gca().yaxis.set_ticks_position('none')\n",
    "    plt.grid(True, which='minor', linestyle='-')\n",
    "    plt.gcf().subplots_adjust(bottom=0.15)\n",
    "\n",
    "    # show confusion matrix\n",
    "    plt.savefig(savename, format='png')\n",
    "    plt.show()\n",
    "def Evaluate(Cmatrixs):\n",
    "\n",
    "    classes = ('NO DR', 'Mild', 'Moderate', 'Severe', 'Proliferative')\n",
    "    n_classes = Cmatrixs.size(0)\n",
    "    Prec, Rec = torch.zeros(n_classes+1), torch.zeros(n_classes+1)\n",
    "\n",
    "    sum_cmt_row = torch.sum(Cmatrixs,dim=1)# 行的和\n",
    "    sum_cmt_col = torch.sum(Cmatrixs,dim=0)# 列的和\n",
    "    print(\"----------------------------------------\")\n",
    "    for i in range(n_classes):\n",
    "        TP = Cmatrixs[i,i]\n",
    "        FN = sum_cmt_row[i] - TP\n",
    "        FP = sum_cmt_col[i] - TP\n",
    "        # TN = torch.sum(Cmatrixs) - sum_cmt_row[i] - FP\n",
    "        Prec[i] = TP / (TP + FP)\n",
    "        Rec[i]  = TP / (TP + FN)\n",
    "        print(\"%s\"%(classes[i]).ljust(10,\" \"),\"Presion=%.3f%%,     Recall=%.3f%%\"%(Prec[i],Rec[i]))\n",
    "\n",
    "    Prec[-1] = torch.mean(Prec[0:-1])\n",
    "    Rec[-1] = torch.mean(Rec[0:-1])\n",
    "    print(\"ALL\".ljust(10,\" \"),\"Presion=%.3f%%,     Recall=%.3f%%\" % (Prec[i], Rec[i]))\n",
    "    print(\"----------------------------------------\")\n",
    "#         return Prec,Rec\n",
    "def MyROC_i(outputs, labels, n=20):\n",
    "    '''\n",
    "    ROC曲线计算 绘制每一类的\n",
    "    Args:\n",
    "        outputs: [num_labels,num_classes]\n",
    "        labels: 标签值\n",
    "        n: 得到n个点之后绘图\n",
    "    Returns:plot_roc\n",
    "    '''\n",
    "\n",
    "    n_total, n_classes = outputs.size()\n",
    "    labels = labels.reshape(-1,1) # 行向量转为列向量\n",
    "    T = torch.linspace(0, 1, n)\n",
    "    TPR, FPR = torch.zeros(n, n_classes+1), torch.zeros(n, n_classes+1)\n",
    "\n",
    "    for i in range(n_classes):\n",
    "        for j in range(n):\n",
    "            mask_1 = outputs[:, i].cpu() > T[j]\n",
    "            TP_FP = torch.sum(mask_1)\n",
    "            mask_2 = (labels[:, -1].cpu() == i)\n",
    "            TP = torch.sum(mask_1 & mask_2)\n",
    "            FN = n_total / n_classes - TP\n",
    "            FP = TP_FP - TP\n",
    "            TN = n_total - n_total / n_classes - FP\n",
    "\n",
    "            TPR[j,i] = TP / (TP + FN)\n",
    "            FPR[j,i] = FP / (FP + TN)\n",
    "\n",
    "    TPR[:,-1] = torch.mean(TPR[:,0:-1],dim=1)\n",
    "    FPR[:, -1] = torch.mean(FPR[:, 0:-1], dim=1)\n",
    "\n",
    "    return TPR,FPR\n",
    "\n",
    "def Plot_ROC_i(TPR, FPR):\n",
    "    for i in range(5+1):\n",
    "        if i==5: width=2\n",
    "        else: width=1\n",
    "        plt.plot(FPR[:,i],\n",
    "                 TPR[:,i],\n",
    "                 linewidth=width,\n",
    "                 label='classes_%d'%(i))\n",
    "                \n",
    "    plt.legend()\n",
    "    plt.title(\"ROC\")\n",
    "    plt.grid(True)\n",
    "    plt.xlim(0,1)\n",
    "    plt.ylim(0,1)\n",
    "    plt.savefig(r'./_ROC_i.png')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "labels_value, predicted_value, outputs_value = [],[],[]\n",
    "correct = 0\n",
    "total = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DataParallel(\n",
       "  (module): MobileNetV3_large(\n",
       "    (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "    (bn1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (layers): Sequential(\n",
       "      (0): Bottleneck(\n",
       "        (conv1): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=16, bias=False)\n",
       "        (bn2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(16, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (1): Bottleneck(\n",
       "        (conv1): Conv2d(16, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=64, bias=False)\n",
       "        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(64, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (2): Bottleneck(\n",
       "        (conv1): Conv2d(24, 72, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(72, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(72, 72, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=72, bias=False)\n",
       "        (bn2): BatchNorm2d(72, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(72, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (3): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=72, out_features=18, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=18, out_features=72, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(24, 72, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(72, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(72, 72, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=72, bias=False)\n",
       "        (bn2): BatchNorm2d(72, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(72, 40, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (4): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=120, out_features=30, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=30, out_features=120, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(40, 120, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(120, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(120, 120, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=120, bias=False)\n",
       "        (bn2): BatchNorm2d(120, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(120, 40, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (5): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=120, out_features=30, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=30, out_features=120, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(40, 120, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(120, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(120, 120, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=120, bias=False)\n",
       "        (bn2): BatchNorm2d(120, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(120, 40, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(40, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (6): Bottleneck(\n",
       "        (conv1): Conv2d(40, 240, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(240, 240, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=240, bias=False)\n",
       "        (bn2): BatchNorm2d(240, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(240, 80, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (7): Bottleneck(\n",
       "        (conv1): Conv2d(80, 200, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(200, 200, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=200, bias=False)\n",
       "        (bn2): BatchNorm2d(200, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(200, 80, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (8): Bottleneck(\n",
       "        (conv1): Conv2d(80, 184, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(184, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(184, 184, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=184, bias=False)\n",
       "        (bn2): BatchNorm2d(184, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(184, 80, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (9): Bottleneck(\n",
       "        (conv1): Conv2d(80, 184, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(184, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(184, 184, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=184, bias=False)\n",
       "        (bn2): BatchNorm2d(184, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(184, 80, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(80, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (10): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=480, out_features=120, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=120, out_features=480, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(80, 480, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(480, 480, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=480, bias=False)\n",
       "        (bn2): BatchNorm2d(480, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(480, 112, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential(\n",
       "          (0): Conv2d(80, 112, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "          (1): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        )\n",
       "      )\n",
       "      (11): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=672, out_features=168, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=168, out_features=672, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(112, 672, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(672, 672, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=672, bias=False)\n",
       "        (bn2): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(672, 112, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(112, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (12): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=672, out_features=168, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=168, out_features=672, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(112, 672, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(672, 672, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=672, bias=False)\n",
       "        (bn2): BatchNorm2d(672, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(672, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (13): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=960, out_features=240, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=240, out_features=960, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(960, 960, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=960, bias=False)\n",
       "        (bn2): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(960, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "      (14): Bottleneck(\n",
       "        (se): SEModule(\n",
       "          (avg_pool): AdaptiveAvgPool2d(output_size=1)\n",
       "          (se): Sequential(\n",
       "            (0): Linear(in_features=960, out_features=240, bias=False)\n",
       "            (1): ReLU(inplace)\n",
       "            (2): Linear(in_features=240, out_features=960, bias=False)\n",
       "          )\n",
       "        )\n",
       "        (conv1): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv2): Conv2d(960, 960, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=960, bias=False)\n",
       "        (bn2): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (conv3): Conv2d(960, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "        (bn3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "        (shortcut): Sequential()\n",
       "      )\n",
       "    )\n",
       "    (conv2): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
       "    (bn2): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (conv3): Conv2d(960, 1280, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (conv4): Conv2d(1280, 5, kernel_size=(1, 1), stride=(1, 1))\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net = MobileNetV3_large()\n",
    "net=nn.DataParallel(net)\n",
    "net.eval()\n",
    "net.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.load_state_dict(torch.load(r'/home/fanrz/Desktop/testlarge/weights/best326.pkl'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import random\n",
    "from PIL import Image\n",
    "from torch.utils.data import Dataset\n",
    "\n",
    "random.seed(1)\n",
    "\n",
    "class flowerDataset(Dataset):\n",
    "    # 自定义Dataset类，必须继承Dataset并重写__init__和__getitem__函数\n",
    "    def __init__(self, data_dir, transform=None):\n",
    "        \"\"\"\n",
    "            花朵分类任务的Dataset\n",
    "            :param data_dir: str, 数据集所在路径\n",
    "            :param transform: torch.transform，数据预处理，默认不进行预处理\n",
    "        \"\"\"\n",
    "        # data_info存储所有图片路径和标签（元组的列表），在DataLoader中通过index读取样本\n",
    "        self.data_info = self.get_img_info(data_dir)\n",
    "        self.transform = transform\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        path_img, label = self.data_info[index]\n",
    "        # 打开图片，默认为PIL，需要转成RGB\n",
    "        img = Image.open(path_img).convert('RGB')\n",
    "        # 如果预处理的条件不为空，应该进行预处理操作\n",
    "        if self.transform is not None:\n",
    "            img = self.transform(img)\n",
    "        return img, label\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.data_info)\n",
    "\n",
    "    # 自定义方法，用于返回所有图片的路径以及标签\n",
    "    @staticmethod\n",
    "    def get_img_info(data_dir):\n",
    "        data_info = list()\n",
    "        for root, dirs, _ in os.walk(data_dir):\n",
    "            # 遍历类别\n",
    "            for sub_dir in dirs:\n",
    "                # listdir为列出文件夹下所有文件和文件夹名\n",
    "                img_names = os.listdir(os.path.join(root, sub_dir))\n",
    "                # 过滤出所有后缀名为jpg的文件名（那当然也就把文件夹过滤掉了）\n",
    "#                 img_names = list(filter(lambda x: x.endswith('.png'), img_names))\n",
    "\n",
    "                # 遍历图片\n",
    "                for i in range(len(img_names)):\n",
    "                    img_name = img_names[i]\n",
    "                    path_img = os.path.join(root, sub_dir, img_name)\n",
    "                    # 在该任务中，文件夹名等于标签名\n",
    "                    label = sub_dir\n",
    "                    data_info.append((path_img, int(label)))\n",
    "        return data_info\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "valid_dir=r'/home/fanrz/Desktop/testlarge/aptos/val2/'\n",
    "valid_transform=transforms.Compose([\n",
    "    transforms.Resize((224,224)),\n",
    "    transforms.ToTensor(),\n",
    "])\n",
    "valid_data=flowerDataset(data_dir=valid_dir,transform=valid_transform)\n",
    "valid_loader=DataLoader(dataset=valid_data,batch_size=64,drop_last=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "924\n"
     ]
    }
   ],
   "source": [
    "print(len(valid_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i,data in enumerate(valid_loader):\n",
    "    images,labels=data\n",
    "    images=images.cuda()\n",
    "    labels=labels.cuda()\n",
    "    outputs=net(images)\n",
    "    _,predicted = torch.max(outputs.data,1) # tensor([0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3], device='cuda:0')\n",
    "    total=total+labels.size(0)\n",
    "    correct=correct+(predicted==labels).sum()\n",
    "#     print(correct) #tensor(14, device='cuda:0')\n",
    "    if i==0:\n",
    "        labels_value = labels\n",
    "        predicted_value = predicted\n",
    "        outputs_value = F.softmax(outputs.data,dim=1)\n",
    "    else:\n",
    "        labels_value = torch.cat((labels_value,labels),0)\n",
    "        predicted_value = torch.cat((predicted_value,predicted),0)\n",
    "        outputs_value = torch.cat((outputs_value,F.softmax(outputs.data,dim=1)),0)\n",
    "correct = correct.cpu().numpy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"acc=%.5f%%\" % (100 * correct / total))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Cmatrixs = Confusion_mxtrix(labels_value,predicted_value,5)\n",
    "print(Cmatrixs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Evaluate(Cmatrixs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TPR_i, FPR_i = MyROC_i(outputs_value, labels_value)\n",
    "Plot_ROC_i(TPR_i, FPR_i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def kappa(matrix):\n",
    "    matrix=np.array(matrix)\n",
    "    n=np.sum(matrix)\n",
    "    sum_po=0\n",
    "    sum_pe=0\n",
    "    for i in range(len(matrix[0])):\n",
    "        sum_po+=matrix[i][i]\n",
    "        row=np.sum(matrix[i,:])\n",
    "        col=np.sum(matrix[:,i])\n",
    "        sum_pe+=row*col\n",
    "    po=sum_po/n\n",
    "    pe=sum_pe/(n*n)\n",
    "    return (po-pe)/(1-pe)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "kappa(Cmatrixs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
